from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np
import sympy as sp
from docx.shared import Cm
from docxtpl import DocxTemplate, InlineImage
from sympy import expand
from sympy2subdoc import sympy_expr_to_subdoc

SCRIPT_TO_INSERT_PATH = "utils/sympy2subdoc.py"
print("start")
# ----------ИСХОДНЫЕ ДАННЫЕ----------
E = 0.68 * 10**11
ro = 2700.0
h = 0.0025
L = 0.5
R = 1.25
P = 300000
mu = 0.3

d = (E * h**3) / (12 * (1 - mu**2))
k = ((E * h) / (d * R**2)) ** (1 / 4)

# ----------ФУНКЦИИ----------

C1, C2, C3, C4 = sp.symbols("C1 C2 C3 C4")
s, ss, e = sp.symbols("s, ss, e")


def w(s: float) -> sp.Expr:
    """Вычисляет функцию w(s) для заданного значения s

    Parameters
    ----------
    s : float
        Значение s, м

    Returns
    -------
    sp.Expr
        Результат вычисления функции w(s) для заданного значения s
    """
    return (
        sp.exp(k * s) * (C1 * sp.cos(k * s) + C2 * sp.sin(k * s))
        + sp.exp(-k * s) * (C3 * sp.cos(k * s) + C4 * sp.sin(k * s))
        + (P * R**2) / (E * h)
    )


def dw(s: float) -> sp.Expr:
    """Вычисляет производную функции w(s) по s

    Parameters
    ----------
    s : float
        Значение s, м

    Returns
    -------
    sp.Expr
        Результат вычисления производной функции w(s) по s
    """
    return sp.diff(w(ss), ss).subs(ss, s)


def ddw(s: float) -> sp.Expr:
    """Вычисляет вторую производную функции w(s) по s для заданного значения s.

    Parameters
    ----------
    s : float
        Значение s, м

    Returns
    -------
    sp.Expr
        Результат вычисления второй производной функции w(s) по s
    """
    return sp.diff(dw(ss), ss).subs(ss, s)


def u(s: float) -> sp.Expr:
    """Вычисляет функции u(s) по s

    Parameters
    ----------
    s : float
        Значение s, м

    Returns
    -------
    sp.Expr
        Результат вычисления функции u(s) по s
    """
    return -mu / R * sp.integrate(w(ss), ss).subs(ss, s)


def plots(
    data2: np.ndarray,
    im_path: str,
    docx_path: str,
    ylab: str,
) -> InlineImage:
    """Cтроит график функции

    Parameters
    ----------
    data2 : np.ndarray
        Массив точек по оси ординат
    im_path : str
        Путь к временному изображению
    docx_path : str
        Путь к документу
    ylab : str
        Подпись оси ординат

    Returns
    -------
    InlineImage
        Встроенное изображение графика в документе
    """
    fig = plt.figure()
    plt.plot(s_data, data2)
    plt.grid(True)
    plt.xlabel("s, м")
    plt.ylabel(ylab)
    fig.savefig(im_path, dpi=fig.dpi)
    return InlineImage(docx_path, str(im_path), Cm(12))


equations = [
    sp.Eq(w(0), 0),
    sp.Eq(dw(0), 0),
    sp.Eq(w(L), 0),
    sp.Eq(dw(L), 0),
]


solution = sp.solve(equations, (C1, C2, C3, C4))

C1, C2, C3, C4 = solution[C1], solution[C2], solution[C3], solution[C4]

OUTPUT_FOLDER = Path("dz/stroimech_obolochka_45")
DOCX_TEMPLATE_PATH = OUTPUT_FOLDER.joinpath("template.docx")
REPORT_OUTPUT_PATH = OUTPUT_FOLDER.joinpath("generated_report.docx")
TEMPORARY_IMAGE1_PATH = OUTPUT_FOLDER.joinpath("image1.png")
TEMPORARY_IMAGE2_PATH = OUTPUT_FOLDER.joinpath("image2.png")
TEMPORARY_IMAGE3_PATH = OUTPUT_FOLDER.joinpath("image3.png")
TEMPORARY_IMAGE4_PATH = OUTPUT_FOLDER.joinpath("image4.png")
TEMPORARY_IMAGE5_PATH = OUTPUT_FOLDER.joinpath("image5.png")

docx_template = DocxTemplate(DOCX_TEMPLATE_PATH)


s_data = np.arange(0.0, L + L / 50, L / 50)
w_data = np.array([w(s) for s in s_data])
u_data = np.array([u(s) for s in s_data])
T2_data = np.array([(E * h / R) * w(s) for s in s_data])
M1_data = np.array([-d * ddw(s) for s in s_data])
M2_data = np.array([-d * mu * ddw(s) for s in s_data])

# тест новой функции
image1 = plots(
    w_data,
    TEMPORARY_IMAGE1_PATH,
    docx_template,
    "w(s), м",
)
image2 = plots(
    u_data,
    TEMPORARY_IMAGE2_PATH,
    docx_template,
    "u(s), м",
)
image3 = plots(
    T2_data,
    TEMPORARY_IMAGE3_PATH,
    docx_template,
    "T2(s), Н/м",
)
image4 = plots(
    M1_data,
    TEMPORARY_IMAGE4_PATH,
    docx_template,
    "M1(s), Н",
)
image5 = plots(
    M2_data,
    TEMPORARY_IMAGE5_PATH,
    docx_template,
    "M2(s), Н",
)

U = u(L) - u(0)

pR, E, h, k = sp.symbols("pR, E, h, k")
expr = (round(C3, 4) * sp.cos(k * s) + round(C4, 4) * sp.sin(k * s)) * (
    e ** (-k * s)
) + (pR**2) / (E * h)

expanded_formula = sympy_expr_to_subdoc(expand(expr), docx_template=docx_template)


context = {
    "image1": image1,
    "image2": image2,
    "image3": image3,
    "image4": image4,
    "image5": image5,
    "C1": round(C1, 4),
    "C2": round(C2, 4),
    "C3": round(C3, 4),
    "C4": round(C4, 4),
    "formula_ws": expanded_formula,
    "u": round(U, 5),
}

# Render automated report
docx_template.render(context)
docx_template.save(REPORT_OUTPUT_PATH)

print("\n" + "-----------------------done-------------------------------")
